﻿' Copyright (C) 2015 HTTPBuilder
'
' This program is free software: you can redistribute it and/or modify it under the +terms 
' of the GNU General Public License as published by the Free Software Foundation, either 
' version 3 of the License, or (at your option) any later version.

' This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
' without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
' See the GNU General Public License for more details.

' You should have received a copy of the GNU General Public License along with this program.
' If not, see http://www.gnu.org/licenses/. 

''' <summary>
''' 
''' </summary>
''' <remarks></remarks>
Public NotInheritable Class StringWalker

#Region "Member Variables"
    Private ReadOnly _s As String
    Private _index As Integer
    Private _isEscaped As Boolean
    Private _currentChar As Char
#End Region

#Region "Constructor"
    ''' <summary>
    ''' 
    ''' </summary>
    ''' <param name="input"></param>
    ''' <remarks></remarks>
    Public Sub New(input As String)
        _s = input
        Me.Index = -1
    End Sub
#End Region

#Region "Public properties"
    ''' <summary>
    ''' 
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Property Index() As Integer
        Get
            Return _index
        End Get
        Private Set(value As Integer)
            _index = value
        End Set
    End Property

    ''' <summary>
    ''' 
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Property IsEscaped() As Boolean
        Get
            Return _isEscaped
        End Get
        Private Set(value As Boolean)
            _isEscaped = value
        End Set
    End Property

    ''' <summary>
    ''' 
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Property CurrentChar() As Char
        Get
            Return _currentChar
        End Get
        Private Set(value As Char)
            _currentChar = value
        End Set
    End Property

    ''' <summary>
    ''' Reads the previous char without advancing the position.
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public ReadOnly Property PreviousChar As Char
        Get
            If Me.Index = 0 Then
                Return Me.CurrentChar
            End If
            Return _s(Index - 1)
        End Get
    End Property

    ''' <summary>
    ''' Reads the next char without advancing the position.
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public ReadOnly Property NextChar As Char
        Get
            If Me.Index = _s.Length - 1 Then
                Return Me.CurrentChar
            End If
            Return _s(Index + 1)
        End Get
    End Property
#End Region

#Region "Public methods"
    ''' <summary>
    ''' 
    ''' </summary>
    ''' <param name="numChars"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function ReadNext(numChars As Integer) As String
        If (Me.Index + numChars) = (_s.Length - 1) Then
            Return ""
        End If

        Dim nextString As String = ""
        For i As Integer = 1 To numChars
            nextString += _s(Index + i)
        Next

        Return nextString
    End Function

    ''' <summary>
    ''' Advances the position to the previous char.
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function MovePrevious() As Boolean
        If Me.Index = 0 Then
            Return False
        End If

        Me.Index -= 1
        CurrentChar = _s(Index)
        Return True
    End Function

    ''' <summary>
    ''' Advances the position to the next char.
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function MoveNext() As Boolean
        If Me.Index = _s.Length - 1 Then
            Return False
        End If

        If IsEscaped = False Then
            IsEscaped = CurrentChar = "\"
        Else
            IsEscaped = False
        End If
        Me.Index += 1
        CurrentChar = _s(Index)
        Return True
    End Function
#End Region
End Class
